package com.dingup.paike.service.message.impl;

import com.alibaba.fastjson.JSON;
import com.dingup.api.Util.DateUtil;
import com.dingup.api.model.classInfo.ClassInfo;
import com.dingup.api.model.classInfo.ClassUserInfo;
import com.dingup.paike.adapter.pk.PkLessonUserAdapter;
import com.dingup.paike.adapter.pk.message.RemindOfClassForUser;
import com.dingup.paike.bean.aobean.MasterSignInAO;
import com.dingup.paike.dao.PkLessonInfoMapper;
import com.dingup.paike.dao.PkLessonStudentSignMapper;
import com.dingup.paike.dao.PkLessonUserMapper;
import com.dingup.paike.dao.PkMessageDetailsMapper;
import com.dingup.paike.enums.MessageUserIdentityEnum;
import com.dingup.paike.enums.PkLessonUserTypeEnum;
import com.dingup.paike.feign.client.classInfo.ClassInfoFeignClient;
import com.dingup.paike.feign.client.user.UserFeignClient;
import com.dingup.paike.model.message.PkMessageDetails;
import com.dingup.paike.model.pk.PkLessonInfo;
import com.dingup.paike.model.pk.PkLessonStudentSign;
import com.dingup.paike.model.pk.PkLessonUser;
import com.dingup.paike.service.message.UserRemindService;
import com.dingup.paike.service.message.WxMsgService;
import com.dingup.util.GDateUtil;
import org.apache.commons.lang.time.DateUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.*;
import java.util.stream.Collectors;

/**
 * Created by wancheng on 2018/10/18.
 */
@Service
public class UserRemindServiceImpl implements UserRemindService {

    private static final String STUDENT_SIGN_IN_MSG = "%s 已签到";
    private static final String STUDENT_SIGN_IN = "签到";
    private static Logger logger = LoggerFactory.getLogger(UserRemindServiceImpl.class);
    @Autowired
    PkLessonUserMapper pkLessonUserMapper;
    @Autowired
    ClassInfoFeignClient classInfoFeignClient;
    @Autowired
    PkMessageDetailsMapper pkMessageDetailsMapper;
    @Autowired
    PkLessonStudentSignMapper pkLessonStudentSignMapper;
    @Autowired
    UserFeignClient userFeignClient;
    @Autowired
    PkLessonInfoMapper pkLessonInfoMapper;
    @Autowired
    WxMsgService wxMsgService;

    /**
     * 上课提醒内容为次天数据
     *
     * @param userId
     * @param typeEnum
     * @return
     */
    @Override
    public RemindOfClassForUser getRemindOfClassForUser(String userId, PkLessonUserTypeEnum typeEnum, String pkMessageDetailsId) {
        PkMessageDetails pkMessageDetails = pkMessageDetailsMapper.selectByPrimaryKey(pkMessageDetailsId);
        //此处修改为发送消息的当天时间
        Date currentDate = pkMessageDetails.getCreateTime();
        Date today = DateUtils.truncate(currentDate, Calendar.DAY_OF_MONTH);
        Date tomorrow = DateUtils.addDays(today, 1);
        String day = DateUtil.date2Str(tomorrow, "MM月dd日");
        String weekDay = DateUtil.getFormatWeek(tomorrow);
        RemindOfClassForUser remind = pkLessonUserMapper.getRemindOfClassForUser(userId, typeEnum, DateUtil.date2Str(tomorrow, "yyyy-MM-dd"));
        if (remind != null) {
            remind.setWeekDay(weekDay);
            remind.setToday(day);
            setPkLessonUserAdapter(remind, typeEnum);
            remind.setIfReceiveConfirm(pkMessageDetails.getIfReceiveConfirm());
        }
        return remind;
    }

    private void setPkLessonUserAdapter(RemindOfClassForUser remind, PkLessonUserTypeEnum typeEnum) {
        if (!CollectionUtils.isEmpty(remind.getLessons())) {
            remind.getLessons().stream().forEach(
                    l -> {
                        ClassInfo classInfo = classInfoFeignClient.getSimpleClassInfo(l.getClassId());
                        l.setClassName(classInfo.getClassName());
                        String begin = DateUtil.date2Str(l.getBeginTime(), "HH:mm");
                        String end = DateUtil.date2Str(l.getEndTime(), "HH:mm");
                        l.setBegin(begin);
                        l.setEnd(end);
                        if (PkLessonUserTypeEnum.MASTER.equals(typeEnum)) {
                            Integer confirmNum = pkMessageDetailsMapper.getConfirmNumByLessonId(l.getPkLessonId());
                            Integer total = pkLessonUserMapper.getMemberCountExceptMaster(l.getPkLessonId());
                            l.setConfirmNum(confirmNum);
                            l.setUserTotal(total);
                        }
                    }
            );
        }
    }

    /**
     * 签到表 的内容为当天的数据
     *
     * @param userId
     * @return
     */
    @Override
    public RemindOfClassForUser getPkLessonSignIn(String userId, String pkMessageDetailsId) {
        PkMessageDetails pkMessageDetails = pkMessageDetailsMapper.selectByPrimaryKey(pkMessageDetailsId);
        //此处修改为发送消息的当天时间
        Date currentDate = pkMessageDetails.getCreateTime();
        Date today = DateUtils.truncate(currentDate, Calendar.DAY_OF_MONTH);
        String day = DateUtil.date2Str(today, "MM月dd日");
        String weekDay = DateUtil.getFormatWeek(today);
        RemindOfClassForUser remind = pkLessonUserMapper.getRemindOfClassForUser(userId, PkLessonUserTypeEnum.MASTER, DateUtil.date2Str(today, "yyyy-MM-dd"));
        if (remind != null) {
            remind.setWeekDay(weekDay);
            remind.setToday(day);
            setPkLessonUserAdapter(remind, PkLessonUserTypeEnum.MASTER);
        }
        return remind;
    }

    @Override
    public MasterSignInAO getPkLessonSignInDetails(Integer pkLessonId) {
        PkLessonUserAdapter pkLesson = getPkLessonUserAdapter(pkLessonId);
        Integer confirmNum = pkMessageDetailsMapper.getConfirmNumByLessonId(pkLesson.getPkLessonId());
        Integer total = pkLessonUserMapper.getMemberCountExceptMaster(pkLesson.getPkLessonId());
        pkLesson.setConfirmNum(confirmNum);
        pkLesson.setUserTotal(total);
        ClassInfo classInfo = classInfoFeignClient.getSimpleClassInfo(pkLesson.getClassId());
        pkLesson.setClassName(classInfo.getClassName());
        //以上为课程基本信息
        //班级所有的学生
        List<ClassUserInfo> allStudents = classInfo.getStudents();
        //该课节需要签到的学生
        List<PkLessonUser> lessonUser = pkLessonUserMapper.getPkLessonUserByPkLessonIdAndType(pkLessonId, PkLessonUserTypeEnum.STUDENT);
        //签到信息
        List<PkLessonStudentSign> signIn = pkLessonStudentSignMapper.getByPkLessonId(pkLessonId);
        //该课节需要签到的学生Id
        List<String> lessonUserIds = lessonUser.stream().map(PkLessonUser::getUserId).collect(Collectors.toList());
        //将签到信息转为map  key->studentId value->PkLessonStudentSign
        Map<String, PkLessonStudentSign> signInMap = signIn.stream().collect(Collectors.toMap(PkLessonStudentSign::getUserId, pkLessonStudentSign -> pkLessonStudentSign));
        MasterSignInAO masterSignInAO = new MasterSignInAO();
        //创建学生签到信息对象----》不需要签到的学生
        List<MasterSignInAO.SignIn> notNeedSignInStudent = allStudents.stream()
                //过滤需要签到的学生
                .filter(u -> !lessonUserIds.contains(u.getUserId()))
                //PkLessonStudentSign --> MasterSignInAO.SignIn
                .map(u -> masterSignInAO.new SignIn(u.getUserId(), u.getUserName()))
                //组合成集合
                .collect(Collectors.toList());
        List<MasterSignInAO.SignIn> needSignInStudent = lessonUser.stream()
                .map(u -> masterSignInAO.new SignIn(u.getUserId(), u.getUserName()))
                .collect(Collectors.toList());

        setStudentSignInMsg(needSignInStudent, signInMap);
        masterSignInAO.setPkLesson(pkLesson);
        masterSignInAO.setNeedSignIn(needSignInStudent);
        masterSignInAO.setNotNeedSignIn(notNeedSignInStudent);
        masterSignInAO.setSignInNum(signIn.size());

        return masterSignInAO;
    }

    /**
     * 课节信息
     *
     * @param pkLessonId
     * @return
     */
    private PkLessonUserAdapter getPkLessonUserAdapter(Integer pkLessonId) {
        Date currentDate = new Date();
        Date today = DateUtils.truncate(currentDate, Calendar.DAY_OF_MONTH);
        String day = DateUtil.date2Str(today, "MM月dd日");
        String weekDay = DateUtil.getFormatWeek(today);
        PkLessonUserAdapter pkLesson = pkLessonUserMapper.getPkLessonAndTeacherMsg(pkLessonId, null);
        String begin = DateUtil.date2Str(pkLesson.getBeginTime(), "HH:mm");
        String end = DateUtil.date2Str(pkLesson.getEndTime(), "HH:mm");
        pkLesson.setDay(day);
        pkLesson.setWeekDay(weekDay);
        pkLesson.setBegin(begin);
        pkLesson.setEnd(end);
        return pkLesson;
    }

    /**
     * 将学生的签到信息放入集合中
     *
     * @param needSignInStudent
     * @param signInMap
     */
    private void setStudentSignInMsg(List<MasterSignInAO.SignIn> needSignInStudent, Map<String, PkLessonStudentSign> signInMap) {
        needSignInStudent.stream().forEach(
                s -> {
                    PkLessonStudentSign sign = signInMap.get(s.getId());
                    if (sign != null) {
                        s.setIfSignIn(true);
                        s.setSignInMsg(String.format(STUDENT_SIGN_IN_MSG, DateUtil.date2Str(sign.getSignTime(), "HH:mm")));
                    } else {
                        s.setIfSignIn(false);
                        s.setSignInMsg(STUDENT_SIGN_IN);
                    }
                }
        );
    }

    @Override
    public void studentSignIn(Integer pkLessonId, String studentId) {
        PkLessonStudentSign studentSign = new PkLessonStudentSign();
        Date currentDate = new Date();
        studentSign.setCreateTime(currentDate);
        studentSign.setSignTime(currentDate);
        studentSign.setIfSign(true);
        studentSign.setPkLessonId(pkLessonId);
        studentSign.setUserId(studentId);
        String studentName = userFeignClient.getUserNameByUserId(studentId);
        studentSign.setUserName(studentName);
        pkLessonStudentSignMapper.insertSelective(studentSign);
        wxMsgService.sendParentWxMsgForStudentSign(studentSign);
    }

    @Override
    public void messageConfirm(String id) {
        PkMessageDetails params = new PkMessageDetails();
        params.setId(id);
        params.setConfirmTime(new Date());
        params.setIfReceiveConfirm(true);
        pkMessageDetailsMapper.updateByPrimaryKeySelective(params);
        logger.info("message confirm params={}", JSON.toJSONString(params));
    }

    @Override
    public MasterSignInAO getPkLessonClassHourConfirmDetails(Integer pkLessonId) {
        MasterSignInAO masterSignInAO = getPkLessonSignInDetails(pkLessonId);
        List<MasterSignInAO.SignIn> needSignIn = masterSignInAO.getNeedSignIn();
        List<MasterSignInAO.SignIn> notNeedSignIn = masterSignInAO.getNotNeedSignIn();
        //不需要上课的学生(不需要签到的学生)
        List<String> notNeedSignInStudent = new ArrayList<>();
        if (!CollectionUtils.isEmpty(notNeedSignIn)) {
            notNeedSignInStudent = notNeedSignIn.stream()
                    .map(MasterSignInAO.SignIn::getName)
                    .collect(Collectors.toList());
        }
        masterSignInAO.setNotNeedSignInStudent(notNeedSignInStudent);
        //对上课的学生进行分组
        Map<Boolean, List<MasterSignInAO.SignIn>> needSignInMap = needSignIn.stream()
                .collect(Collectors.groupingBy(MasterSignInAO.SignIn::getIfSignIn));
        //签到学生
        List<MasterSignInAO.SignIn> signInStudent = needSignInMap.get(true);
        //未签到学生
        List<MasterSignInAO.SignIn> unSignInStudent = needSignInMap.get(false);
        List<String> unSignInStudentName = new ArrayList<>();
        if (!CollectionUtils.isEmpty(unSignInStudent)) {
            unSignInStudentName = unSignInStudent
                    .stream()
                    .map(MasterSignInAO.SignIn::getName)
                    .collect(Collectors.toList());
        }
        masterSignInAO.setUnSignInStudent(unSignInStudentName);
        if (!CollectionUtils.isEmpty(needSignIn)) {
            masterSignInAO.setSignInTotal(needSignIn.size());
        } else {
            masterSignInAO.setSignInTotal(0);
        }
        if (!CollectionUtils.isEmpty(signInStudent)) {
            masterSignInAO.setSignInNum(signInStudent.size());
        } else {
            masterSignInAO.setSignInNum(0);
        }
        masterSignInAO.clean();
        return masterSignInAO;
    }

    @Override
    public void lessonClassHourConfirm(Integer pkLessonId, Boolean ifClassFee, Float classHour) {
        PkLessonInfo pkLessonInfo = new PkLessonInfo();
        pkLessonInfo.setId(pkLessonId);
        pkLessonInfo.setIfLessonFinish(true);
        pkLessonInfoMapper.updateByPrimaryKeySelective(pkLessonInfo);
        List<PkLessonUser> teachers = pkLessonUserMapper.getPkLessonUserByPkLessonIdAndType(pkLessonId, PkLessonUserTypeEnum.TEACHER);
        if (ifClassFee != null && ifClassFee) {
            List<PkLessonUser> studentSigns = pkLessonUserMapper.getPkLessonUserByPkLessonIdAndType(pkLessonId, PkLessonUserTypeEnum.STUDENT);
            if (studentSigns == null) {
                studentSigns = new ArrayList<>();
            }
            List<String> ids = studentSigns.stream()
                    .map(PkLessonUser::getUserId)
                    .distinct()
                    .collect(Collectors.toList());
            List<String> teacherIds = teachers.stream()
                    .map(PkLessonUser::getUserId)
                    .distinct()
                    .collect(Collectors.toList());
            ids.addAll(teacherIds);
            ids.add(pkLessonInfo.getTeacherId());
            pkLessonUserMapper.updateUserClassHourForBatch(pkLessonId, ids, classHour);
        }
    }

    @Override
    public PkLessonUserAdapter getLessonRemindAboutToBegin(Integer pkLessonId) {
        PkLessonUserAdapter pkLessonUserAdapter = getPkLessonUserAdapter(pkLessonId);
        if (pkLessonUserAdapter.getIfOnlineLesson()) {
            pkLessonUserAdapter.setClassRoom("ClassIn");
        }
        ClassInfo classInfo = classInfoFeignClient.getSimpleClassInfo(pkLessonUserAdapter.getClassId());
        pkLessonUserAdapter.setClassName(classInfo.getClassName());
        return pkLessonUserAdapter;
    }

    @Override
    public MasterSignInAO getLessonConfirmDetailsForClass(Integer pkLessonId, String pkMessageDetailsId) {
        //课节基本信息
        MasterSignInAO masterSignInAO = getPkLessonSignInDetails(pkLessonId);
        List<PkLessonUser> lessonTeacher = pkLessonUserMapper.getPkLessonUserByPkLessonIdAndType(pkLessonId, PkLessonUserTypeEnum.TEACHER);

        PkMessageDetails masterDetails = pkMessageDetailsMapper.selectByPrimaryKey(pkMessageDetailsId);
        //钉钉发送消息详情
        List<PkMessageDetails> details = pkMessageDetailsMapper.getByLessonIdAndTime(pkLessonId, GDateUtil.getShortDateStr(masterDetails.getCreateTime()));
        //按照身份进行分组
        Map<MessageUserIdentityEnum, List<PkMessageDetails>> detailsMap = details.stream()
                .collect(Collectors.groupingBy(PkMessageDetails::getUserIdentity));
        List<MasterSignInAO.SignIn> teacherSignIn = lessonTeacher.stream()
                //PkLessonStudentSign --> MasterSignInAO.SignIn
                .map(u -> masterSignInAO.new SignIn(u.getUserId(), u.getUserName()))
                //组合成集合
                .collect(Collectors.toList());

        setConfirmDetails(teacherSignIn, detailsMap.get(MessageUserIdentityEnum.TEACHER));
        setConfirmDetails(masterSignInAO.getNeedSignIn(), detailsMap.get(MessageUserIdentityEnum.STUDENT));
        masterSignInAO.setTeacherSignIn(teacherSignIn);
        return masterSignInAO;
    }

    private void setConfirmDetails(List<MasterSignInAO.SignIn> lessonUsers, List<PkMessageDetails> details) {
        //将list转成 userId->PkMessageDetails
        if (!CollectionUtils.isEmpty(details)) {
            Map<String, PkMessageDetails> detailsMap = details.stream().collect(Collectors.toMap(PkMessageDetails::getUserId, d -> d));
            lessonUsers.stream().forEach(
                    u -> {
                        PkMessageDetails messageDetails = detailsMap.get(u.getId());
                        if (messageDetails.getIfReceiveConfirm()) {
                            u.setIfSignIn(true);
                            u.setSignInMsg("已收到");
                        } else {
                            u.setIfSignIn(false);
                            u.setSignInMsg("未确认");
                        }
                    }
            );
        } else {
            lessonUsers.stream().forEach(u -> {
                u.setIfSignIn(false);
                u.setSignInMsg("未确认");
            });
        }

    }
}
